/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.netbeans.saas.google;

import bean.GeolocalizacionBean;
import bean.LogueoBean;
import datos.Foto;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.netbeans.saas.RestConnection;
import org.netbeans.saas.RestResponse;

/**
 * GoogleMapService Service
 *
 * @author Ing. Monica Merlo, Ing. Agustin  Fernandez
 */
public class GoogleMapService {

    static Logger logger = Logger.getLogger(GoogleMapService.class);

    public static void log4jArchivo (Exception e){
        /**
         * Primero obtenemos la url del archivo de configuración,
         * como están en el mismo paquete que la clase Main lo podemos obtener con el método getResource().
         */
        URL url = GoogleMapService.class.getResource("/configuracion/log4j.properties");
        /**
         * Despues cargamos el archivo de configuración
         */
        PropertyConfigurator.configure(url);
        logger.error(e);
    }

    private static String apiKey;
//    private static final String PROP_FILE = GoogleMapService.class.getSimpleName().toLowerCase() + ".properties";
    private static final String PROP_FILE = "/configuracion/googlemapservice.properties";

    static {
        try {
            Properties props = new Properties();
            props.load(GoogleMapService.class.getResourceAsStream(PROP_FILE));
            apiKey = props.getProperty("api_key");
        } catch (IOException ex) {
            GoogleMapService.log4jArchivo(ex);
        }
    }

    public static String getApiKey() throws IOException {
        if (apiKey == null || apiKey.length() == 0) {
            throw new IOException("Please specify your api key in the " + PROP_FILE + " file.");
        }

        return apiKey;
    }

    /**
     * Returns HTML text to access GoogleMap.
     * @param address - address string to generate map for.
     * @param zoom.
     */
    public static RestResponse getGoogleMap(List fotos, String nombreObra, String codigoObra,
            Date fechaInicioObra, Date fechaFinObra, String montoObra, String estadoObra,
            String nombreEmpresaContratista, String latitud, String longitud, String direccion,
            Integer zoom, String tipoGeocoding) throws IOException {
        try {
            String key = getApiKey();
            String encoded = URLEncoder.encode(direccion, "UTF-8");
            GeoCoder coder = new GeoCoder(encoded, apiKey);
            GeoCode code = coder.invoke();
            double latUsar = 0.0d;
            double longUsar = 0.0d;
            if(tipoGeocoding.equals("geoinverso")){
                latUsar = code.getLatitude();
                longUsar = code.getLongitude();
            } else if(tipoGeocoding.equals("geodirecto")){
                latUsar = Double.parseDouble(latitud);
                longUsar = Double.parseDouble(longitud);
            }

            String mapRep = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'\n" +
                        "  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n" +
                        "<html xmlns='http://www.w3.org/1999/xhtml'>\n" +
                        "  <head>\n" +
                        "    <meta http-equiv='content-type' content='text/html; charset=utf-8'/>\n" +
                        "    <title>Google Maps JavaScript API Example</title>\n" +
                        getMapScript(fotos, nombreObra, codigoObra, fechaInicioObra, fechaFinObra, montoObra, estadoObra, nombreEmpresaContratista, direccion, zoom, latUsar, longUsar, key) +
                        "  </head>\n" +
                        "  <body onload='loadScript()' onunload='GUnload()'>\n" +
                        "    <div id='map' style='width: 640px; height: 480px'></div>\n" +
                        "  </body>\n" +
                        "</html>";
            return new RestResponse(mapRep.getBytes());
        } catch (Exception ex) {
            GoogleMapService.log4jArchivo(ex);
            throw new IOException(ex.getMessage());
        }
    }

    /**
     * Returns HTML text to access GoogleMap.
     * @param address - address string to generate map for.
     * @param zoom.
     */
    public static RestResponse getGoogleMapConCoordenadas(List fotos, String nombreObra, String codigoObra,
            Date fechaInicioObra, Date fechaFinObra, String montoObra,
            String estadoObra, String nombreEmpresaContratista,
            String latitud, String longitud, Integer zoom, String iframe) throws IOException {
        try {
            String key = getApiKey();
            //String encoded = URLEncoder.encode(address, "UTF-8");
            //GeoCoder coder = new GeoCoder(encoded, apiKey);
            GeoCoder coder = new GeoCoder(latitud, longitud, apiKey);
            GeoCode code = coder.invokeConCoordenadas();

            String mapRep = "";
            if (iframe != null && iframe.trim().equalsIgnoreCase("true")) {
                mapRep +=
                        "    <div id='map' style='width: 500px; height: 300px'></div>\n" +
                        //                    getMapScriptConCoordenadas("OBRA", zoom, code.getLatitude(), code.getLongitude(), key)+
                        "    <script type='text/javascript'>\n" +
                        "       loadScript();\n" +
                        "    </script>\n";
            } else {
                mapRep =
                        "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'\n" +
                        "  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n" +
                        "<html xmlns='http://www.w3.org/1999/xhtml'>\n" +
                        "  <head>\n" +
                        "    <meta http-equiv='content-type' content='text/html; charset=utf-8'/>\n" +
                        "    <title>Geolocalizacion de la Obra: " + nombreObra + "</title>\n" +
                        getMapScriptConCoordenadas(fotos, nombreObra, codigoObra, fechaInicioObra, fechaFinObra, montoObra, estadoObra, nombreEmpresaContratista, zoom, code.getLatitude(), code.getLongitude(), key) +
                        "  </head>\n" +
                        "  <body onload='loadScript()' onunload='GUnload()'>\n" +
                        "    <div id='map' style='width: 640px; height: 480px'></div>\n" +
                        "  </body>\n" +
                        "</html>";
            }
            return new RestResponse(mapRep.getBytes());
        } catch (Exception ex) {
            GoogleMapService.log4jArchivo(ex);
            throw new IOException(ex.getMessage());
        }
    }

    public static RestResponse getGoogleMapsConsultaGeo(LogueoBean logueoUsuario, String contextPath, GeolocalizacionBean geo, String nombrePais, List<datos.Obra> obras, Integer zoom) throws IOException {
        try {
            String key = getApiKey();
            if(nombrePais.trim().equals("###")){
                nombrePais="ARGENTINA";
            }
            String encoded = URLEncoder.encode(nombrePais, "UTF-8");
            GeoCoder coder = new GeoCoder(encoded, apiKey);
            GeoCode code = coder.invoke();

            String mapRep = "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'\n" +
                        "  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n" +
                        "<html xmlns='http://www.w3.org/1999/xhtml'>\n" +
                        "  <head>\n" +
                        "    <meta http-equiv='content-type' content='text/html; charset=utf-8'/>\n" +
                        "    <title>Google Maps JavaScript API Example</title>\n" +
                        getMapScriptConsultaGeo(logueoUsuario, contextPath, geo, obras,zoom, code.getLatitude(), code.getLongitude(), key) +
                        "  </head>\n" +
                        "  <body onload='loadScript()' onunload='GUnload()'>\n" +
                        "    <div id='map' style='width: 640px; height: 480px'></div>\n" +
                        "  </body>\n" +
                        "</html>";
            return new RestResponse(mapRep.getBytes());
        } catch (Exception ex) {
            GoogleMapService.log4jArchivo(ex);
            throw new IOException(ex.getMessage());
        }
    }

    public static String getMapScriptConsultaGeo(LogueoBean logueoUsuario, String contextPath, GeolocalizacionBean geo, List <datos.Obra>obras,Integer zoom, double latitude, double longitude, String key) {
        String mapRep =
                "    <script type='text/javascript'>\n" +
                "    //<![CDATA[\n" +
                "    function loadMap() {\n" +
                "      if (GBrowserIsCompatible()) {\n" +
                "        var map = new GMap2(document.getElementById('map'));\n" +
                "        var point = new GLatLng(" + latitude + ", " + longitude + ");\n" +
                "        map.addControl(new GSmallMapControl());\n" +
                "        map.addControl(new GMapTypeControl());\n" +
                "        map.setCenter(point, " + zoom + ");\n" +
                "        map.addMapType(G_PHYSICAL_MAP);\n"+
                "        map.setMapType(G_HYBRID_MAP);\n" +
                parsearMarcadoresParaConsultaGeo(logueoUsuario, contextPath, geo, obras) +
                "      }\n" +
                "    }\n" +
                "    function loadScript() {\n" +
                "      var script = document.createElement(\"script\");\n" +
                "      script.setAttribute(\"src\", \"http://maps.google.com/maps?file=api&v=2.x&key=" + key + "&async=2&callback=loadMap\");\n" +
                "      script.setAttribute(\"type\", \"text/javascript\");\n" +
                "      document.documentElement.firstChild.appendChild(script);\n" +
                "    }\n" +
                "    //]]>\n" +
                "    </script>\n";
        return mapRep;
    }

    public static String parsearMarcadoresParaConsultaGeo(LogueoBean logueoUsuario, String contextPath, GeolocalizacionBean geo, List<datos.Obra> obras) {
        if (obras != null) {
            StringBuffer sb = new StringBuffer();
            int i = 0;
            for (datos.Obra obra : obras) {
                sb.append("var point" + obra.getId() + " = new GLatLng(" + obra.getIdLocalizacion().getLatitud() + ", " + obra.getIdLocalizacion().getLongitud() + ");\n");
                sb.append("var icono = new GIcon(G_DEFAULT_ICON);\n");
                sb.append("icono.image = 'images/iconoObra.png';\n");
                sb.append("icono.iconSize = new GSize(32, 37);\n");
                sb.append("icono.shadow = 'images/sombraIconoObra.png';\n");
                sb.append("icono.shadowSize = new GSize(51, 37);\n");
                sb.append("icono.iconAnchor = new GPoint(15,35);\n");
                sb.append("var marker" + obra.getId() + " = new GMarker(point" + obra.getId() + ", {icon: icono});\n");
                List fotosDeObra = geo.getFotosPorObra(obra.getId());
                String contenidoGlobo = parsearDatosObraParaGloboInfo(logueoUsuario, contextPath, fotosDeObra, obra.getId(), obra.getNombre(), obra.getIdLocalizacion().getCalle()+" "+obra.getIdLocalizacion().getNumero()+" - "+obra.getIdLocalizacion().getIdLocalidad().getNombre()+" - "+obra.getIdLocalizacion().getIdLocalidad().getIdDepartamento().getIdProvincia().getIdPais().getNombre(), obra.getIdTipoObra().getNombre(), obra.getFechaInicioReal(), obra.getFechaFinReal(), obra.getIdEstado().getNombre(), obra.getMontoTotal().toString(), obra.getIdEmpresa().getRazonSocial());
                sb.append("GEvent.addListener(marker"+ obra.getId() +", \"click\", function() {\n" +
                        "         marker"+ obra.getId() +".openInfoWindowHtml(\"" + contenidoGlobo + "\");\n" +
                        "      });\n");
                sb.append("map.addOverlay(marker" + obra.getId() + ");\n");

                /**
                 * Esto es para saber si se debe mostrar o no la ventanita de información
                 * en el mapa Google. Esta debe aparecer cargada en el mapa cuando el
                 * usuario hace click en la tabla de resultados de busqueda que aparece
                 * del lado derecho de la interfaz de consultas de geolocalización.
                 */
                if(geo.getIdObra()!=-1 && geo.getIdObra()==obra.getId().intValue()){
                    sb.append("marker" + obra.getId() + ".openInfoWindowHtml(\"" + contenidoGlobo + "\");\n");
                }

                i++;
                if (i == 100) {
                    break;
                }
            }
            return sb.toString();
        } else {
            return "";
        }
    }

    public static String getMapScript(List fotos, String nombreObra, String codigoObra,
            Date fechaInicioObra, Date fechaFinObra, String montoObra,
            String estadoObra, String nombreEmpresaContratista, String direccion,
            Integer zoom, double latitude, double longitude, String key) {
        String html = "Información no disponible";
        String mapRep =
                "    <script type='text/javascript'>\n" +
                "    //<![CDATA[\n" +
                "    function loadMap() {\n" +
                "      if (GBrowserIsCompatible()) {\n" +
                "        var map = new GMap2(document.getElementById('map'));\n" +
                "        var point = new GLatLng(" + latitude + ", " + longitude + ");\n" +
                "        map.addControl(new GSmallMapControl());\n" +
                "        map.addControl(new GMapTypeControl());\n" +
                "        map.setCenter(point, " + zoom + ");\n" +
                "        map.addMapType(G_PHYSICAL_MAP);\n"+
                "        map.setMapType(G_HYBRID_MAP);\n"+
                "        var marker = createMarker(point);\n" +
                "        GEvent.addListener(marker, \"dragstart\", function() {\n" +
                "                                                   map.closeInfoWindow();\n" +
                "                           });\n" +
                "        GEvent.addListener(marker, \"dragend\", function (){\n" +
                "                                               top.document.forms['frmGeo'].elements['frmGeo:txtLatitudGeo'].value=marker.getPoint().lat();\n" +
                "                                               top.document.forms['frmGeo'].elements['frmGeo:txtLongitudGeo'].value=marker.getPoint().lng();\n" +
                "                                               top.document.forms['frmGeo'].elements['frmGeo:zoomGeo'].value=map.getZoom();\n"+
                "                           });" +
                "       top.document.forms['frmGeo'].elements['frmGeo:txtLatitudGeo'].value=point.lat();\n" +
                "       top.document.forms['frmGeo'].elements['frmGeo:txtLongitudGeo'].value=point.lng();\n" +
                "       top.document.forms['frmGeo'].elements['frmGeo:zoomGeo'].value=map.getZoom();\n" +
                "       map.addOverlay(marker);\n" +
                "      }\n" +
                "    }\n" +
                "    function createMarker(point) {\n" +
                "    var icono = new GIcon(G_DEFAULT_ICON);\n" +
                "    icono.image = 'images/iconoObra.png';\n" +
                "    icono.iconSize = new GSize(32, 37);\n" +
                "    icono.shadow = 'images/sombraIconoObra.png';\n" +
                "    icono.shadowSize = new GSize(51, 37);\n" +
                "    icono.iconAnchor = new GPoint(15,35);\n" +
                "      var marker = new GMarker(point, {icon: icono, draggable: true});"+
                "      GEvent.addListener(marker, \"click\", function() {\n" +
                "      marker.openInfoWindowHtml(\"" + html + "\");\n" +
                "      });\n" +
                "      return marker;\n" +
                "    }\n" +
                "    function loadScript() {\n" +
                "      var script = document.createElement(\"script\");\n" +
                "      script.setAttribute(\"src\", \"http://maps.google.com/maps?file=api&v=2.x&key=" + key + "&async=2&callback=loadMap\");\n" +
                "      script.setAttribute(\"type\", \"text/javascript\");\n" +
                "      document.documentElement.firstChild.appendChild(script);\n" +
                "    }\n" +
                "    //]]>\n" +
                "    </script>\n";
        return mapRep;
    }

    public static String parsearDatosObraParaGloboInfo(LogueoBean logueoUsuario, String contextPath, List fotos, int idObra, String nombreObra, String direccionObra, String tipoObra, Date fechaInicioObra, Date fechaFinObra,
            String estadoObra, String montoObra, String razonEmpresaContratista) {
        StringBuffer sb = new StringBuffer();
        int i = 0;
        SimpleDateFormat sd = new SimpleDateFormat("dd/MM/yyyy");

        sb.append("<table border=0>");
        if(logueoUsuario.isPermisoModObra()){
//            sb.append("<tr><th colspan='4'><font size='2'><u><a href='"+contextPath+"/RedireccionadorServlet?idObram="+idObra+"' target='_parent'>" + nombreObra + "</a></u></font></th></tr>");
              sb.append("<tr><th colspan='4'><font size='2'><u><form name='frmVerGeo' action='"+contextPath+"/RedireccionadorServlet' method='post' target='_parent'><input type='hidden' name='idObram' value='"+idObra+"'><a href='javascript: void(0);' onclick='document.frmVerGeo.submit();return false;'>" + nombreObra + "</a></form></u></font></th></tr>");
        }else{
//            sb.append("<tr><th colspan='4'><font size='2'><u><a href='"+contextPath+"/RedireccionadorServlet?idObrav="+idObra+"' target='_parent'>" + nombreObra + "</a></u></font></th></tr>");
            sb.append("<tr><th colspan='4'><font size='2'><u><form name='frmVerGeo' action='"+contextPath+"/RedireccionadorServlet'  method='post' target='_parent'><input type='hidden' name='idObrav' value='"+idObra+"'><a href='javascript: void(0);' onclick='document.frmVerGeo.submit();return false;'>" + nombreObra + "</a></form></u></font></th></tr>");
        }
        sb.append("<tr>");
        sb.append("<td colspan='1'><font size='1'><b>Ubicaci&oacute;n:</b></font></td><td colspan='3'><font size='1'>" + direccionObra.toUpperCase() + "</font></td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td><font size='1'><b>Tipo:</b></font></td><td><font size='1'>" + tipoObra.toUpperCase() + "</font></td>");
        sb.append("<td><font size='1'><b>Periodo:</b></font></td><td><font size='1'>" + sd.format(fechaInicioObra) + "&nbsp;al&nbsp;" + sd.format(fechaFinObra) + "</font></td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td><font size='1'><b>Estado:</b></font></td><td><font size='1'>" + estadoObra + "</font></td>");
        sb.append("<td><font size='1'><b>Monto &nbsp; $:</b></font></td><td><font size='1'>" + montoObra + "</font></td>");
        sb.append("</tr>");
        sb.append("<tr>");
        sb.append("<td><font size='1'><b>Empresa:</b></font></td><td><font size='1'>" + razonEmpresaContratista + "</font></td>");
        sb.append("</tr>");
        sb.append("</table><br>");

        if (!fotos.isEmpty()) {
            sb.append("<div style='overflow-x: auto; overflow-y: hidden; width: 280px; height:110px;'>");
            sb.append("<table>");
            sb.append("<tr>");
            Iterator iterador = fotos.iterator();

            while (iterador.hasNext()) {
                Foto foto = (Foto) iterador.next();
                sb.append("<td><a target='blank' href='" + foto.getRuta() + "' title='Foto " + i + " --- " + sd.format(foto.getFecha()) + "'><img src='" + foto.getRutaThumbnail() + "'></a></td>");
                i++;
                if (i == 3) {
                    break;
                }
            }
            sb.append("</tr>");
            sb.append("</table>");
            sb.append("</div>");
        }
        return sb.toString();
    }

    public static String getMapScriptConCoordenadas(List fotos, String nombreObra, String codigoObra,
            Date fechaInicioObra, Date fechaFinObra, String montoObra,
            String estadoObra, String nombreEmpresaContratista,
            Integer zoom, double latitude, double longitude, String key) {
        String html = "Información no disponible";
        String mapRep =
                "    <script type='text/javascript'>\n" +
                "    //<![CDATA[\n" +
                "    function loadMap() {\n" +
                "      if (GBrowserIsCompatible()) {\n" +
                "        var map = new GMap2(document.getElementById('map'));\n" +
                "        var point = new GLatLng(" + latitude + ", " + longitude + ");\n" +
                "        map.addControl(new GSmallMapControl());\n" +
                "        map.addControl(new GMapTypeControl());\n" +
                "        map.setCenter(point, " + zoom + ");\n" +
                "        map.addMapType(G_PHYSICAL_MAP);\n"+
                "        map.setMapType(G_HYBRID_MAP);\n"+
                "        var marker = createMarker(point);\n" +
                "        map.addOverlay(marker);\n" +
                "        GEvent.addListener(map, \"click\", function (overlay,point){\n" +
                "                                               if (point){\n" +
                "                                               marker.setPoint(point);\n" +
                "                                               var zoomActual = map.getZoom();\n"+
                "                                               top.document.forms['frmGeo'].elements['frmGeo:txtLatitudGeo'].value=point.lat();\n" +
                "                                               top.document.forms['frmGeo'].elements['frmGeo:txtLongitudGeo'].value=point.lng();\n" +
                "                                               top.document.forms['frmGeo'].elements['frmGeo:zoomGeo'].value=zoomActual;\n"+
                "                                           }\n" +
                "                           });" +
                "        //marker.openInfoWindowHtml(\"" + html + "\");\n" +
                "      }\n" +
                "    }\n" +
                "    function createMarker(point) {\n" +
                "      var marker = new GMarker(point);\n" +
                "      GEvent.addListener(marker, \"click\", function() {\n" +
                "         marker.openInfoWindowHtml(\"" + html + "\");\n" +
                "      });\n" +
                "      return marker;\n" +
                "    }\n" +
                "    function loadScript() {\n" +
                "      var script = document.createElement(\"script\");\n" +
                "      script.setAttribute(\"src\", \"http://maps.google.com/maps?file=api&v=2.x&key=" + key + "&async=2&callback=loadMap\");\n" +
                "      script.setAttribute(\"type\", \"text/javascript\");\n" +
                "      document.documentElement.firstChild.appendChild(script);\n" +
                "    }\n" +
                "    //]]>\n" +
                "    </script>\n";
        return mapRep;
    }

    public static class GeoCoder {

        public final static String GEOCODE_URL = "http://maps.google.com/maps/geo";
        private String location;
        private String key;
        private String latitud;
        private String longitud;

        /** Creates a new instance of GeoCoder */
        public GeoCoder(String location, String key) {
            this.location = location;
            this.key = key;
        }

        /** Creates a new instance of GeoCoder */
        public GeoCoder(String latitud, String longitud, String key) {
            this.latitud = latitud;
            this.longitud = longitud;
            this.key = key;
        }

        /**
         *
         * @return geocode
         */
        public GeoCode invoke() throws IOException {
            String[][] params = new String[][]{
                {"q", location},
                {"output", "xml"},
                {"key", key}
            };
            RestConnection cl = new RestConnection(GEOCODE_URL, params);
            RestResponse response = cl.get();
            String codeStr = response.getDataAsString();
            return new GeoCode(codeStr);
        }

        /**
         *
         * @return geocode
         */
        public GeoCode invokeConCoordenadas() throws IOException {
            String[][] params = new String[][]{
                {"ll", latitud + "," + longitud},
                {"output", "xml"},
                {"key", key}
            };
            RestConnection cl = new RestConnection(GEOCODE_URL, params);
            RestResponse response = cl.get();
            String codeStr = response.getDataAsString();
            return new GeoCode(codeStr);
        }
    }

    public static class GeoCode {

        private double longitude;
        private double latitude;

        /** Creates a new instance of GeoCode */
        public GeoCode(String xmlStr) {
            int ts = xmlStr.indexOf("<coordinates>");
            int te = xmlStr.indexOf("</coordinates>");
            String codeStr = "";
            if (ts != -1 && te != -1) {
                codeStr = xmlStr.substring(ts + 13, te);
                
            }
            String[] codes = codeStr.split(",");
            if (codes.length > 1) {
                this.longitude = Double.parseDouble(codes[0]);
                this.latitude = Double.parseDouble(codes[1]);
            }
        }

        /**
         *
         * @return longitude
         */
        public double getLongitude() {
            return this.longitude;
        }

        /**
         *
         * @return latitude
         */
        public double getLatitude() {
            return this.latitude;
        }
    }
}
